home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
admin
/
linuxcon.000
/
linuxcon
/
linuxconf-1.6
/
dialog
/
multi.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-08-01
|
10KB
|
452 lines
#include <stdio.h>
#include <string.h>
#include "diadef.h"
#include "dialog.h"
#include "internal.h"
/*
Evaluate the size of a text in a string.
(number of line, maximum width)
The string may contain tabs.
Return the number of line
*/
int dialog_textsize (const char *txt, int *width)
{
int nbline=1;
int maxlen = 0;
if (txt != NULL){
const char *lastpt = txt;
char *pt = strchr (txt,'\n');
while (pt != NULL){
int len = 0;
while (lastpt < pt){
if (*lastpt == '\t'){
if (len % 8 == 0) len++;
while (len % 8 != 0) len++;
}else{
len++;
}
lastpt++;
}
len += 2;
nbline++;
if (len > maxlen) maxlen = len;
lastpt = pt+1;
pt = strchr (lastpt,'\n');
}
{
int lastlen = strlen (lastpt);
if (lastlen > maxlen) maxlen = lastlen;
}
}
*width = maxlen;
return nbline;
}
/*
Open a centered window
*/
WINDOW *dialog_openwin(
int height,
int width)
{
WINDOW *dialog;
if (COLS == 0){
fprintf (stderr,"You forget init_dialog\n");
exit (-1);
}else{
/* center dialog box on screen */
int x = (COLS - width)/2;
int y = (LINES - height)/2;
// Open larger to draw the shadow
int height_1 = height+1;
if (height_1 > LINES) height_1 = LINES;
int width_2 = width+2;
if (width_2 > COLS) width_2 = COLS;
dialog = newwin(height_1, width_2, y, x);
keypad(dialog, TRUE);
}
return dialog;
}
void dialog_draw (
WINDOW *dialog,
const char *title,
const char *intro,
int height,
int width)
{
draw_box(dialog, 0, 0, height, width, dialog_attr
, border_attr, border_attr_shadow);
draw_shadow(dialog, 0, 0, height, width);
if (title != NULL) {
wattrset(dialog, title_attr);
wmove(dialog, 0, (width - strlen(title))/2 - 1);
waddch(dialog, ' ');
waddstr(dialog, (char*)title);
waddch(dialog, ' ');
}
if (intro != NULL){
int posy = 1;
while (*intro != '\0'){
char tmp[100];
char *pt = tmp;
while (*intro != '\0' && *intro != '\n'){
*pt++ = *intro++;
}
*pt = '\0';
if (*intro == '\n') intro++;
wmove (dialog,posy++,2);
waddstr (dialog,tmp);
}
}
}
/*
Compute the layout of the dialog based on its content.
*/
PRIVATE void DIALOG::setup ()
{
int fields_height = getnb()==0 ? 0 : getnb()+2;
int button_height = 3;
int frame_space = 3;
int max_prompt = 0;
int intro_height= 0;
int intro_width = 0;
if (!intro.is_empty()){
intro_height = dialog_textsize(intro.get(),&intro_width);
intro_width += 4;
}
nbvisible = getnb();
height = intro_height + frame_space + button_height + fields_height;
if (height > 24){
nbvisible -= height - 24;
height = 24;
}
int max_field = 0;
for (int i=0; i<getnb(); i++){
FIELD *f = getitem(i);
char *prompt = f->prompt;
int len = strlen(prompt);
if (len > max_prompt) max_prompt = len;
f->box.y = 3 + intro_height + i - offset;
if (max_field < f->box.width) max_field = f->box.width;
}
int data_width = max_field + 5 + max_prompt;
width = data_width;
if (width < intro_width) width = intro_width;
int title_len = title.getlen();
int button_len = buttons->evalwidth();
if (title_len > width) width = title_len;
if (button_len > width) width = button_len;
buttons->setup (height-3,width);
// Try to center the data box if there is no prompt
if (data_width < width && max_prompt < 2){
max_prompt += (width - data_width)/2;
}
for (i=0; i<getnb(); i++){
FIELD *f = getitem(i);
f->box.x = max_prompt + 3;
f->box.width = max_field;
}
}
/*
Set the offset of the first visible field and ajust
the coordinate of all field so they will know where to draw
themselve.
*/
PRIVATE void DIALOG::setoffset (int newoff)
{
int diff = newoff - offset;
offset = newoff;
for (int i=0; i<getnb(); i++){
getitem(i)->box.y -= diff;
}
}
/*
Draw all visible field
*/
PROTECTED void DIALOG::drawf(WINDOW *dialog)
{
int lastf = getnb();
if (lastf - offset > nbvisible) lastf = offset + nbvisible;
for (int i=offset; i<lastf; i++){
getitem(i)->draw (dialog);
}
}
/*
Send a message to all fields of a dialog
*/
PRIVATE void DIALOG::processmsg(WINDOW *dialog, FIELD_MSG &msg)
{
int lastf = getnb();
int last_visible = offset + nbvisible;
for (int i=0; i<lastf; i++){
getitem(i)->processmsg (dialog,msg
,i >= offset && i < last_visible);
}
}
/*
Draw the complete dialog
*/
PRIVATE void DIALOG::draw (WINDOW *dialog)
{
dialog_draw (dialog,title.get(),intro.get(),height,width);
wattrset(dialog, dialog_attr);
if (getnb()>0){
/* Draw the input field box */
FIELD *finfo = getitem(offset);
draw_box(dialog, finfo->box.y-1, finfo->box.x-1, nbvisible+2
, finfo->box.width+2
, inputbox_attr, border_attr_shadow,border_attr);
drawf(dialog);
}
buttons->draw (dialog,button);
}
PRIVATE void DIALOG::drawarrow_if(
WINDOW *win,
bool condition, // Should it be drawn
bool & flag, // Does the carac is already drawn
bool top, // Top or bottom arrow
chtype carac) // Char to print
{
if (getnb() > 0){
FIELD *f = getitem(offset);
int posx = f->box.x + f->box.width/2;
int posy = top ? f->box.y - 1 : f->box.y + nbvisible;
if (condition){
if (!flag){
flag = true;
wmove (win,posy,posx);
wattrset(win,inputbox_border_attr);
waddch (win,carac);
}
}else if (flag){
flag = false;
wmove (win,posy,posx);
wattrset(win,inputbox_border_attr);
waddch (win,ACS_HLINE);
}
}
}
/*
Interpret a cursor key.
Return -1 if it not a cursor key
*/
PROTECTED VIRTUAL int DIALOG::keymove (WINDOW *dialog, int key, int &nof)
{
int ret = 0;
switch (key){
case KEY_PPAGE:
if (offset == 0){
nof = 0;
}else{
int newoff = offset - nbvisible;
if (newoff < 0) newoff = 0;
nof -= (offset - newoff);
setoffset(newoff);
drawf(dialog);
}
break;
case KEY_UP:
nof--;
if (nof < offset){
if (offset > 0){
setoffset(offset -1);
drawf(dialog);
}else{
nof = 0;
}
}
break;
case KEY_NPAGE:
{
int maxoffset = getnb() - nbvisible;
if (maxoffset < 0) maxoffset = 0;
if (offset >= maxoffset){
nof = getnb()-1;
}else{
int newoff = offset + nbvisible;
if (newoff > maxoffset) newoff = maxoffset;
nof += (newoff - offset);
setoffset(newoff);
drawf(dialog);
}
}
break;
case KEY_DOWN:
nof++;
if (nof < getnb()){
if (nof == offset + nbvisible){
setoffset (offset+1);
drawf(dialog);
}
}else{
nof--;
}
break;
default:
ret = -1;
}
return ret;
}
DIALOG_MODE dialog_mode = DIALOG_CURSES;
/*
Set the basic user interface mode.
This function is generally called at startup time
*/
void dialog_setmode (DIALOG_MODE mode)
{
dialog_mode = mode;
}
PUBLIC DIALOG::DIALOG()
{
buttons = new BUTTONS_INFO;
offset = 0;
}
PUBLIC DIALOG::~DIALOG()
{
html_forgetdialog (this);
delete buttons;
}
/*
Multiple field dialog.
All field are shown one under each others
*/
PUBLIC MENU_STATUS DIALOG::edit(
const char *_title, // Main title
const char *_intro, // Mini help describing the purpose
// of the dialog
const char *helpfile, // Help text in a file or NULL
int &nof, // Start editing on which field
// Will contain the current field.
int but_options) // MENUBUT_xxxxx
{
MENU_STATUS ret = MENU_NULL;
button = getnb()==0 ? 0 : -1; // Button currently selected
title.setfrom (_title);
intro.setfrom (_intro);
buttons->set (but_options,helpfile);
setup ();
if (dialog_mode == DIALOG_HTML){
ret = edithtml (nof);
}else{
ret = editterm (nof,but_options);
}
if (ret == MENU_ACCEPT){
/* Save the content of the edit field into the buffer */
save();
}
return ret;
}
/*
Multiple field dialog.
All field are shown one under each others
*/
PUBLIC MENU_STATUS DIALOG::edit(
const char *_title, // Main title
const char *_intro, // Mini help describing the purpose
// of the dialog
HELP_FILE &helpfile, // Help text in a file or NULL
int &nof, // Start editing on which field
// Will contain the current field.
int but_options) // MENUBUT_xxxxx
{
return edit (_title,_intro,helpfile.getpath(),nof,but_options);
}
/*
Multiple field dialog.
All field are shown one under each others
*/
PUBLIC MENU_STATUS DIALOG::edit(
const char *_title, // Main title
const char *intro, // Mini help describing the purpose
// of the dialog
const char *helpfile, // Help text in a file or NULL
int nof) // Start editing on which field
{
return edit (_title,intro,helpfile,nof
,MENUBUT_ACCEPT|MENUBUT_CANCEL);
}
/*
Multiple field dialog.
All field are shown one under each others
*/
PUBLIC MENU_STATUS DIALOG::edit(
const char *_title, // Main title
const char *intro, // Mini help describing the purpose
// of the dialog
HELP_FILE &helpfile, // Help text in a file or NULL
int nof) // Start editing on which field
{
return edit (_title,intro,helpfile.getpath(),nof);
}
#ifdef TEST
#include "../translate/translat.h"
int main (int argc, char *argv[])
{
translat_load ("/tmp","linuxconf-msg-" REVISION ".eng");
init_dialog();
DIALOG dia;
char str1[80]; str1[0] = '\0';
char str2[100]; strcpy (str2,"Hello");
SSTRING pass;
char addr[10]; addr[0] = '\0';
dia.newf_str ("Question 1",str1,sizeof(str1)-1);
dia.newf_str ("Other",str2,sizeof(str2)-1);
char chk = 0;
dia.newf_chk ("Option",chk,"more option");
dia.newf_pass ("Password",pass);
dia.newf_str ("Address",addr,sizeof(addr)-1);
SSTRING addr2;
FIELD_COMBO *comb = dia.newf_combo ("Combo",addr2);
comb->addopt("opt 1");
comb->addopt("opt 2");
comb->addopt("opt 3");
comb->addopt("opt 4");
SSTRING addr3;
dia.newf_str ("sstring",addr3);
dia.edit ("This is a test",NULL,NULL,0);
dia.newf_str ("Other",str2,sizeof(str2)-1);
dia.newf_str ("Other",str2,sizeof(str2)-1);
dia.newf_str ("Other",str2,sizeof(str2)-1);
dia.newf_str ("Other",str2,sizeof(str2)-1);
dia.newf_str ("Other",str2,sizeof(str2)-1);
dia.newf_str ("Other",str2,sizeof(str2)-1);
dia.newf_str ("Other",str2,sizeof(str2)-1);
dia.newf_str ("Other",str2,sizeof(str2)-1);
dialog_settimeout (15,MENU_ESCAPE,1);
dia.edit ("This is a test"
,"Please you must reenter the\n"
"value\n"
"or accept it\n"
,"helpfile"
,2);
endwin();
printf ("Question 1 :%s:\n",str1);
printf ("Other :%s:\n",str2);
printf ("Option :%s:\n",chk ? "Selected" : "Not selected");
printf ("Password :%s:\n",pass.get());
printf ("Address :%s:\n",addr);
printf ("Address 2 :%s:\n",addr2.get());
printf ("Address 3 :%s:\n",addr3.get());
return 0;
}
#endif